﻿using System.Text;
using System.Xml;
using System.IO;

namespace Utility
{
    /// <summary>
    /// 本类提供配置文件读写支持
    /// <para/>
    /// 格式:<see cref="System.Xml"/>
    /// <para/>
    /// 默认编码:<see cref="Encoding.UTF8"/>
    /// </summary>
    public static class XmlSerializer
    {
        /// <summary>
        /// 文件读写时使用的默认编码格式
        /// </summary>
        public static Encoding DefaultEncoding { get; set; } = Encoding.UTF8;

        /// <summary>
        /// 本类的核心基础函数
        /// <para/>
        /// 负责把<see cref="object"/>序列化后写到<see cref="Stream"/>中
        /// </summary>
        /// <param name="Stream">建议值:<see cref="FileStream"/>和<see cref="MemoryStream"/></param>
        /// <param name="Target">需要序列化的目标</param>
        /// <remarks>似乎不支持<see cref="Dictionary{TKey, TValue}"/></remarks>
        public static void BaseSerialize(Stream Stream, object Target) => new System.Xml.Serialization.XmlSerializer(Target.GetType()).Serialize(XmlWriter.Create(Stream, new XmlWriterSettings()
        {
            Indent = true,
            NewLineChars = System.Environment.NewLine,
            Encoding = DefaultEncoding,
            IndentChars = "\t",
            NamespaceHandling = NamespaceHandling.OmitDuplicates
        }), Target);

        /// <summary>
        /// 将<see cref="object"/>序列化成格式为<see cref="System.Xml"/>的<see cref="string"/>
        /// </summary>
        /// <param name="Target">序列化目标对象</param>
        /// <returns></returns>
        public static string Serialize(object Target)
        {
            using (MemoryStream Stream = new MemoryStream())
            {
                BaseSerialize(Stream, Target);

                Stream.Position = 0;
                return new StreamReader(Stream, DefaultEncoding).ReadToEnd();
            }
        }

        /// <summary>
        /// 将<see cref="object"/>序列化成格式为<see cref="System.Xml"/>的<see cref="string"/>
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="Target">序列化目标对象</param>
        /// <returns></returns>
        public static string Serialize<T>(T Target)
        {
            using (MemoryStream stream = new MemoryStream())
            {
                BaseSerialize(stream, Target);
                stream.Position = 0;
                return new StreamReader(stream, DefaultEncoding).ReadToEnd();
            }
        }

        /// <summary>
        /// 从XML字符串中反序列化对象
        /// </summary>
        /// <typeparam name="T">结果对象类型</typeparam>
        /// <param name="str">包含对象的XML字符串</param>
        /// <returns>反序列化得到的对象</returns>
        public static T Deserialize<T>(string str) => (T)new System.Xml.Serialization.XmlSerializer(typeof(T)).Deserialize(new StreamReader(new MemoryStream(DefaultEncoding.GetBytes(str)), DefaultEncoding));

        /// <summary>
        /// 将一个对象按XML序列化的方式写入到一个文件
        /// </summary>
        /// <param name="Target">要序列化的对象</param>
        /// <param name="Path">保存文件路径</param>
        public static void SerializeToFile(object Target, string Path)
        {
            using (FileStream file = new FileStream(Path, FileMode.Create, FileAccess.Write))
            {
                BaseSerialize(file, Target);
            }
        }

        /// <summary>
        /// 读入一个文件，并按XML的方式反序列化对象。
        /// </summary>
        /// <typeparam name="T">结果对象类型</typeparam>
        /// <param name="Path">文件路径</param>
        /// <returns>反序列化得到的对象</returns>.
        public static T DeserializeFromFile<T>(string Path) => Deserialize<T>(File.ReadAllText(Path, DefaultEncoding));
    }
}
